/**
 * 
 */
package fr.toussna.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import fr.toussna.dao.ArticleDAO;
import fr.toussna.dao.CommentDAO;
import fr.toussna.entity.Article;
import fr.toussna.entity.Category;
import fr.toussna.entity.Comment;
import fr.toussna.entity.Member;
import fr.toussna.exception.ElementNotExistException;
import fr.toussna.exception.ObjectNotFoundException;
import fr.toussna.service.ArticleService;

/**
 * Cette classe est l'implémentation de l'interface de service
 * {@link ArticleService}
 * 
 * @author My
 * @version 2.0
 * 
 */
public class ArticleServiceImpl implements ArticleService {

	private static final Log LOGGER = LogFactory.getLog(ArticleServiceImpl.class.getName());

	// **********************************
	// * Dependances *
	// **********************************
	/**
	 * Bean pour accéder aux données. Spring IOC
	 */
	ArticleDAO articledao;

	/**
	 * Bean pour accéder aux données. Spring IOC
	 */
	CommentDAO commentdao;

	// **********************************
	// * Methodes Hertiees *
	// **********************************

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.toussna.service.ArticleService#searchArticle(java.lang.String)
	 */
	@Override
	public List<Article> searchArticle(String key) {

		List liste = articledao.selectByKey(key);
		if (LOGGER.isDebugEnabled()) {
			LOGGER.info(" Searching by word: " + key + "\n returned result: " + liste);
		}
		return liste;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * fr.toussna.service.ArticleService#addArticle(fr.toussna.entity.Article)
	 */
	@Override
	public Article addArticle(Article article) {

		final SimpleDateFormat utc = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
		article.setDate(utc.format(new Date()));
		Long id = (Long) articledao.insert(article);
		article.setId(id);
		articledao.insertToCache(article);

		if (LOGGER.isDebugEnabled()) {
			LOGGER.info("Adding article: " + article + "\n returned id: " + id);
		}
		return article;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * fr.toussna.service.ArticleService#deleteArticle(fr.toussna.entity.Article
	 * )
	 */
	@Override
	public void deleteArticle(Article article) {

		articledao.delete(article);
		if (article.getComments() != null) {
			for (Comment com : article.getComments()) {
				commentdao.delete(com);
			}
		}
		if (LOGGER.isDebugEnabled()) {
			LOGGER.info(" Deleting an article: " + article);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * fr.toussna.service.ArticleService#updateArticle(fr.toussna.entity.Article
	 * )
	 */
	@Override
	public void updateArticle(Article article) {

		articledao.update(article);
		articledao.insertToCache(article);
		if (LOGGER.isDebugEnabled()) {
			LOGGER.info("Updating article: " + article);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.toussna.service.ArticleService#findArticle(long)
	 */
	@Override
	public Article findArticle(long id) throws ElementNotExistException {

		Article article = (Article) articledao.selectCachedElement(id, Article.class.getCanonicalName());
		try {
			if (article == null) {
				article = (Article) articledao.select(id);
			}
			// Rajout des commetaires attaches.
			List listCom = commentdao.selectAllByArticle(article);
			article.setComments(listCom);
			if (LOGGER.isDebugEnabled()) {
				LOGGER.info(" Finding article with id: " + id + "\n returned article: " + article + "\n attached comments: " + article.getComments());
			}
		} catch (ObjectNotFoundException e) {
			LOGGER.error("Article id not found" + id, e);
			throw new ElementNotExistException(e);
		}
		return article;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * fr.toussna.service.ArticleService#addComment(fr.toussna.entity.Comment)
	 */
	@Override
	public Comment addComment(Comment comment) throws ElementNotExistException {

		Long id = (Long) commentdao.insert(comment);
		comment.setId(id);
		Article article;
		article = (Article) findArticle(comment.getArticle().getId());

		if (article.getComments() == null) {
			article.setComments(new ArrayList<Comment>());
		}
		article.getComments().add(comment);
		articledao.insertToCache(article);

		if (LOGGER.isDebugEnabled()) {
			LOGGER.info("Adding a comment:" + comment + "\n returned id: " + id);
		}
		return comment;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * fr.toussna.service.ArticleService#getCategoryOfArticle(fr.toussna.entity
	 * .Category)
	 */
	@Override
	public List<Article> getCategoryOfArticle(Category category) {

		List liste = articledao.selectByCategory(category);

		if (LOGGER.isDebugEnabled()) {
			LOGGER.info("Articles of a category: " + category + "\n returned artilces: " + liste);
		}
		return liste;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * fr.toussna.service.ArticleService#findArticleOfMember(fr.toussna.entity
	 * .Member)
	 */
	@Override
	public List<Article> findArticleOfMember(Member member) {

		List liste = articledao.selectByMember(member);

		if (LOGGER.isDebugEnabled()) {
			LOGGER.info("Articles of a member: " + member + "\n returned articles: " + liste);
		}
		return liste;
	}

	// **********************************
	// * Getters & Setters *
	// **********************************
	/**
	 * Utilisé par Spring IOC
	 * 
	 * @param articledao
	 *            L'articleDAO a setter
	 */
	public void setArticledao(ArticleDAO articledao) {
		this.articledao = articledao;
	}

	/**
	 * Utilisé par Spring IOC
	 * 
	 * @param articledao
	 *            L'articleDAO a setter
	 */
	public void setCommentdao(CommentDAO commentdao) {
		this.commentdao = commentdao;
	}

}
